home *** CD-ROM | disk | FTP | other *** search
/ Enter 2006 September / Enter 09 2006.iso / Internet / SpamExperts Home 1.1 / SpamExperts Home.exe / lib / spamexperts.modules / TiffImagePlugin.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2006-07-14  |  18.5 KB  |  665 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.4)
  3.  
  4. __version__ = '1.3.4'
  5. import Image
  6. import ImageFile
  7. import ImagePalette
  8. import string
  9.  
  10. def il16(c, o = 0):
  11.     return ord(c[o]) + (ord(c[o + 1]) << 8)
  12.  
  13.  
  14. def il32(c, o = 0):
  15.     return ord(c[o]) + (ord(c[o + 1]) << 8) + (ord(c[o + 2]) << 16) + (ord(c[o + 3]) << 24)
  16.  
  17.  
  18. def ol16(i):
  19.     return chr(i & 255) + chr(i >> 8 & 255)
  20.  
  21.  
  22. def ol32(i):
  23.     return chr(i & 255) + chr(i >> 8 & 255) + chr(i >> 16 & 255) + chr(i >> 24 & 255)
  24.  
  25.  
  26. def ib16(c, o = 0):
  27.     return ord(c[o + 1]) + (ord(c[o]) << 8)
  28.  
  29.  
  30. def ib32(c, o = 0):
  31.     return ord(c[o + 3]) + (ord(c[o + 2]) << 8) + (ord(c[o + 1]) << 16) + (ord(c[o]) << 24)
  32.  
  33. IMAGEWIDTH = 256
  34. IMAGELENGTH = 257
  35. BITSPERSAMPLE = 258
  36. COMPRESSION = 259
  37. PHOTOMETRIC_INTERPRETATION = 262
  38. FILLORDER = 266
  39. IMAGEDESCRIPTION = 270
  40. STRIPOFFSETS = 273
  41. SAMPLESPERPIXEL = 277
  42. ROWSPERSTRIP = 278
  43. STRIPBYTECOUNTS = 279
  44. X_RESOLUTION = 282
  45. Y_RESOLUTION = 283
  46. PLANAR_CONFIGURATION = 284
  47. RESOLUTION_UNIT = 296
  48. SOFTWARE = 305
  49. DATE_TIME = 306
  50. ARTIST = 315
  51. PREDICTOR = 317
  52. COLORMAP = 320
  53. EXTRASAMPLES = 338
  54. SAMPLEFORMAT = 339
  55. JPEGTABLES = 347
  56. COPYRIGHT = 33432
  57. IPTC_NAA_CHUNK = 33723
  58. PHOTOSHOP_CHUNK = 34377
  59. COMPRESSION_INFO = {
  60.     1: 'raw',
  61.     2: 'tiff_ccitt',
  62.     3: 'group3',
  63.     4: 'group4',
  64.     5: 'tiff_lzw',
  65.     6: 'tiff_jpeg',
  66.     7: 'jpeg',
  67.     32771: 'tiff_raw_16',
  68.     32773: 'packbits' }
  69. OPEN_INFO = {
  70.     (0, 1, 1, (1,), ()): ('1', '1;I'),
  71.     (0, 1, 2, (1,), ()): ('1', '1;IR'),
  72.     (0, 1, 1, (8,), ()): ('L', 'L;I'),
  73.     (0, 1, 2, (8,), ()): ('L', 'L;IR'),
  74.     (1, 1, 1, (1,), ()): ('1', '1'),
  75.     (1, 1, 2, (1,), ()): ('1', '1;R'),
  76.     (1, 1, 1, (8,), ()): ('L', 'L'),
  77.     (1, 1, 1, (8, 8), (2,)): ('LA', 'LA'),
  78.     (1, 1, 2, (8,), ()): ('L', 'L;R'),
  79.     (1, 1, 1, (16,), ()): ('I;16', 'I;16'),
  80.     (1, 2, 1, (16,), ()): ('I;16S', 'I;16S'),
  81.     (1, 2, 1, (32,), ()): ('I', 'I;32S'),
  82.     (1, 3, 1, (32,), ()): ('F', 'F;32F'),
  83.     (2, 1, 1, (8, 8, 8), ()): ('RGB', 'RGB'),
  84.     (2, 1, 2, (8, 8, 8), ()): ('RGB', 'RGB;R'),
  85.     (2, 1, 1, (8, 8, 8, 8), (0,)): ('RGBX', 'RGBX'),
  86.     (2, 1, 1, (8, 8, 8, 8), (1,)): ('RGBA', 'RGBa'),
  87.     (2, 1, 1, (8, 8, 8, 8), (2,)): ('RGBA', 'RGBA'),
  88.     (2, 1, 1, (8, 8, 8, 8), (999,)): ('RGBA', 'RGBA'),
  89.     (3, 1, 1, (1,), ()): ('P', 'P;1'),
  90.     (3, 1, 2, (1,), ()): ('P', 'P;1R'),
  91.     (3, 1, 1, (2,), ()): ('P', 'P;2'),
  92.     (3, 1, 2, (2,), ()): ('P', 'P;2R'),
  93.     (3, 1, 1, (4,), ()): ('P', 'P;4'),
  94.     (3, 1, 2, (4,), ()): ('P', 'P;4R'),
  95.     (3, 1, 1, (8,), ()): ('P', 'P'),
  96.     (3, 1, 1, (8, 8), (2,)): ('PA', 'PA'),
  97.     (3, 1, 2, (8,), ()): ('P', 'P;R'),
  98.     (5, 1, 1, (8, 8, 8, 8), ()): ('CMYK', 'CMYK'),
  99.     (6, 1, 1, (8, 8, 8), ()): ('YCbCr', 'YCbCr'),
  100.     (8, 1, 1, (8, 8, 8), ()): ('LAB', 'LAB') }
  101. PREFIXES = [
  102.     'MM\x00*',
  103.     'II*\x00']
  104.  
  105. def _accept(prefix):
  106.     return prefix[:4] in PREFIXES
  107.  
  108.  
  109. class ImageFileDirectory:
  110.     
  111.     def __init__(self, prefix = 'II'):
  112.         self.prefix = prefix[:2]
  113.         if self.prefix == 'MM':
  114.             self.i16 = ib16
  115.             self.i32 = ib32
  116.         elif self.prefix == 'II':
  117.             self.i16 = il16
  118.             self.i32 = il32
  119.             self.o16 = ol16
  120.             self.o32 = ol32
  121.         else:
  122.             raise SyntaxError('not a TIFF IFD')
  123.         self.reset()
  124.  
  125.     
  126.     def reset(self):
  127.         self.tags = { }
  128.         self.tagdata = { }
  129.         self.next = None
  130.  
  131.     
  132.     def keys(self):
  133.         return self.tagdata.keys() + self.tags.keys()
  134.  
  135.     
  136.     def items(self):
  137.         items = self.tags.items()
  138.         for tag in self.tagdata.keys():
  139.             items.append((tag, self[tag]))
  140.         
  141.         return items
  142.  
  143.     
  144.     def __len__(self):
  145.         return len(self.tagdata) + len(self.tags)
  146.  
  147.     
  148.     def __getitem__(self, tag):
  149.         
  150.         try:
  151.             return self.tags[tag]
  152.         except KeyError:
  153.             (type, data) = self.tagdata[tag]
  154.             (size, handler) = self.load_dispatch[type]
  155.             self.tags[tag] = data = handler(self, data)
  156.             del self.tagdata[tag]
  157.             return data
  158.  
  159.  
  160.     
  161.     def get(self, tag, default = None):
  162.         
  163.         try:
  164.             return self[tag]
  165.         except KeyError:
  166.             return default
  167.  
  168.  
  169.     
  170.     def getscalar(self, tag, default = None):
  171.         
  172.         try:
  173.             value = self[tag]
  174.             if len(value) != 1:
  175.                 if tag == SAMPLEFORMAT:
  176.                     raise KeyError
  177.                 
  178.                 raise ValueError, 'not a scalar'
  179.             
  180.             return value[0]
  181.         except KeyError:
  182.             if default is None:
  183.                 raise 
  184.             
  185.             return default
  186.  
  187.  
  188.     
  189.     def has_key(self, tag):
  190.         if not self.tags.has_key(tag):
  191.             pass
  192.         return self.tagdata.has_key(tag)
  193.  
  194.     
  195.     def __setitem__(self, tag, value):
  196.         if type(value) is not type(()):
  197.             value = (value,)
  198.         
  199.         self.tags[tag] = value
  200.  
  201.     load_dispatch = { }
  202.     
  203.     def load_byte(self, data):
  204.         l = []
  205.         for i in range(len(data)):
  206.             l.append(ord(data[i]))
  207.         
  208.         return tuple(l)
  209.  
  210.     load_dispatch[1] = (1, load_byte)
  211.     
  212.     def load_string(self, data):
  213.         if data[-1:] == '\x00':
  214.             data = data[:-1]
  215.         
  216.         return data
  217.  
  218.     load_dispatch[2] = (1, load_string)
  219.     
  220.     def load_short(self, data):
  221.         l = []
  222.         for i in range(0, len(data), 2):
  223.             l.append(self.i16(data, i))
  224.         
  225.         return tuple(l)
  226.  
  227.     load_dispatch[3] = (2, load_short)
  228.     
  229.     def load_long(self, data):
  230.         l = []
  231.         for i in range(0, len(data), 4):
  232.             l.append(self.i32(data, i))
  233.         
  234.         return tuple(l)
  235.  
  236.     load_dispatch[4] = (4, load_long)
  237.     
  238.     def load_rational(self, data):
  239.         l = []
  240.         for i in range(0, len(data), 8):
  241.             l.append((self.i32(data, i), self.i32(data, i + 4)))
  242.         
  243.         return tuple(l)
  244.  
  245.     load_dispatch[5] = (8, load_rational)
  246.     
  247.     def load_undefined(self, data):
  248.         return data
  249.  
  250.     load_dispatch[7] = (1, load_undefined)
  251.     
  252.     def load(self, fp):
  253.         self.reset()
  254.         i16 = self.i16
  255.         i32 = self.i32
  256.         for i in range(i16(fp.read(2))):
  257.             ifd = fp.read(12)
  258.             tag = i16(ifd)
  259.             typ = i16(ifd, 2)
  260.             if Image.DEBUG:
  261.                 import TiffTags
  262.                 tagname = TiffTags.TAGS.get(tag, 'unknown')
  263.                 typname = TiffTags.TYPES.get(typ, 'unknown')
  264.                 print 'tag: %s (%d)' % (tagname, tag), '- type: %s (%d)' % (typname, typ),
  265.             
  266.             
  267.             try:
  268.                 dispatch = self.load_dispatch[typ]
  269.             except KeyError:
  270.                 if Image.DEBUG:
  271.                     print '- unsupported type', typ
  272.                     continue
  273.                 continue
  274.  
  275.             (size, handler) = dispatch
  276.             size = size * i32(ifd, 4)
  277.             if size > 4:
  278.                 here = fp.tell()
  279.                 fp.seek(i32(ifd, 8))
  280.                 data = ImageFile._safe_read(fp, size)
  281.                 fp.seek(here)
  282.             else:
  283.                 data = ifd[8:8 + size]
  284.             if len(data) != size:
  285.                 raise IOError, 'not enough data'
  286.             
  287.             self.tagdata[tag] = (typ, data)
  288.             if Image.DEBUG:
  289.                 if tag in (COLORMAP, IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK):
  290.                     print '- value: <table: %d bytes>' % size
  291.                 else:
  292.                     print '- value:', self[tag]
  293.             tag in (COLORMAP, IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK)
  294.         
  295.         self.next = i32(fp.read(4))
  296.  
  297.     
  298.     def save(self, fp):
  299.         o16 = self.o16
  300.         o32 = self.o32
  301.         fp.write(o16(len(self.tags)))
  302.         tags = self.tags.items()
  303.         tags.sort()
  304.         directory = []
  305.         append = directory.append
  306.         offset = fp.tell() + len(self.tags) * 12 + 4
  307.         stripoffsets = None
  308.         for tag, value in tags:
  309.             if Image.DEBUG:
  310.                 import TiffTags
  311.                 tagname = TiffTags.TAGS.get(tag, 'unknown')
  312.                 print 'save: %s (%d)' % (tagname, tag), '- value:', value
  313.             
  314.             if type(value[0]) is type(''):
  315.                 typ = 2
  316.                 data = value = string.join(value, '\x00') + '\x00'
  317.             elif tag == STRIPOFFSETS:
  318.                 stripoffsets = len(directory)
  319.                 typ = 4
  320.             elif tag in (X_RESOLUTION, Y_RESOLUTION):
  321.                 typ = 5
  322.             else:
  323.                 typ = 3
  324.                 for v in value:
  325.                     if v >= 65536:
  326.                         typ = 4
  327.                         continue
  328.                 
  329.             if typ == 3:
  330.                 data = string.join(map(o16, value), '')
  331.             else:
  332.                 data = string.join(map(o32, value), '')
  333.             if len(data) == 4:
  334.                 append((tag, typ, len(value), data, ''))
  335.                 continue
  336.             if len(data) < 4:
  337.                 append((tag, typ, len(value), data + (4 - len(data)) * '\x00', ''))
  338.                 continue
  339.             count = len(value)
  340.             if typ == 5:
  341.                 count = count / 2
  342.             
  343.             append((tag, typ, count, o32(offset), data))
  344.             offset = offset + len(data)
  345.             if offset & 1:
  346.                 offset = offset + 1
  347.                 continue
  348.         
  349.         if stripoffsets is not None:
  350.             (tag, typ, count, value, data) = directory[stripoffsets]
  351.             if not not data:
  352.                 raise AssertionError, 'multistrip support not yet implemented'
  353.             value = o32(self.i32(value) + offset)
  354.             directory[stripoffsets] = (tag, typ, count, value, data)
  355.         
  356.         for tag, typ, count, value, data in directory:
  357.             if Image.DEBUG > 1:
  358.                 print tag, typ, count, repr(value), repr(data)
  359.             
  360.             fp.write(o16(tag) + o16(typ) + o32(count) + value)
  361.         
  362.         fp.write('\x00\x00\x00\x00')
  363.         for tag, typ, count, value, data in directory:
  364.             fp.write(data)
  365.             if len(data) & 1:
  366.                 fp.write('\x00')
  367.                 continue
  368.         
  369.         return offset
  370.  
  371.  
  372.  
  373. class TiffImageFile(ImageFile.ImageFile):
  374.     format = 'TIFF'
  375.     format_description = 'Adobe TIFF'
  376.     
  377.     def _open(self):
  378.         '''Open the first image in a TIFF file'''
  379.         ifh = self.fp.read(8)
  380.         if ifh[:4] not in PREFIXES:
  381.             raise SyntaxError, 'not a TIFF file'
  382.         
  383.         self.tag = self.ifd = ImageFileDirectory(ifh[:2])
  384.         self._TiffImageFile__first = self._TiffImageFile__next = self.ifd.i32(ifh, 4)
  385.         self._TiffImageFile__frame = -1
  386.         self._TiffImageFile__fp = self.fp
  387.         self._seek(0)
  388.  
  389.     
  390.     def seek(self, frame):
  391.         '''Select a given frame as current image'''
  392.         if frame < 0:
  393.             frame = 0
  394.         
  395.         self._seek(frame)
  396.  
  397.     
  398.     def tell(self):
  399.         '''Return the current frame number'''
  400.         return self._tell()
  401.  
  402.     
  403.     def _seek(self, frame):
  404.         self.fp = self._TiffImageFile__fp
  405.         if frame < self._TiffImageFile__frame:
  406.             self._TiffImageFile__frame = -1
  407.             self._TiffImageFile__next = self._TiffImageFile__first
  408.         
  409.         while self._TiffImageFile__frame < frame:
  410.             if not self._TiffImageFile__next:
  411.                 raise EOFError, 'no more images in TIFF file'
  412.             
  413.             self.fp.seek(self._TiffImageFile__next)
  414.             self.tag.load(self.fp)
  415.             self._TiffImageFile__next = self.tag.next
  416.             self._TiffImageFile__frame = self._TiffImageFile__frame + 1
  417.         self._setup()
  418.  
  419.     
  420.     def _tell(self):
  421.         return self._TiffImageFile__frame
  422.  
  423.     
  424.     def _decoder(self, rawmode, layer):
  425.         '''Setup decoder contexts'''
  426.         args = None
  427.         if rawmode == 'RGB' and self._planar_configuration == 2:
  428.             rawmode = rawmode[layer]
  429.         
  430.         compression = self._compression
  431.         if compression == 'raw':
  432.             args = (rawmode, 0, 1)
  433.         elif compression == 'jpeg':
  434.             args = (rawmode, '')
  435.             if self.tag.has_key(JPEGTABLES):
  436.                 self.tile_prefix = self.tag[JPEGTABLES]
  437.             
  438.         elif compression == 'packbits':
  439.             args = rawmode
  440.         elif compression == 'tiff_lzw':
  441.             args = rawmode
  442.             if self.tag.has_key(317):
  443.                 self.decoderconfig = (self.tag[PREDICTOR][0],)
  444.             
  445.         
  446.         return args
  447.  
  448.     
  449.     def _setup(self):
  450.         '''Setup this image object based on current tags'''
  451.         getscalar = self.tag.getscalar
  452.         self._compression = COMPRESSION_INFO[getscalar(COMPRESSION, 1)]
  453.         self._planar_configuration = getscalar(PLANAR_CONFIGURATION, 1)
  454.         photo = getscalar(PHOTOMETRIC_INTERPRETATION, 0)
  455.         fillorder = getscalar(FILLORDER, 1)
  456.         if Image.DEBUG:
  457.             print '*** Summary ***'
  458.             print '- compression:', self._compression
  459.             print '- photometric_interpretation:', photo
  460.             print '- planar_configuration:', self._planar_configuration
  461.             print '- fill_order:', fillorder
  462.         
  463.         xsize = getscalar(IMAGEWIDTH)
  464.         ysize = getscalar(IMAGELENGTH)
  465.         self.size = (xsize, ysize)
  466.         if Image.DEBUG:
  467.             print '- size:', self.size
  468.         
  469.         format = getscalar(SAMPLEFORMAT, 1)
  470.         key = (photo, format, fillorder, self.tag.get(BITSPERSAMPLE, (1,)), self.tag.get(EXTRASAMPLES, ()))
  471.         if Image.DEBUG:
  472.             print 'format key:', key
  473.         
  474.         
  475.         try:
  476.             (self.mode, rawmode) = OPEN_INFO[key]
  477.         except KeyError:
  478.             if Image.DEBUG:
  479.                 print '- unsupported format'
  480.             
  481.             raise SyntaxError, 'unknown pixel mode'
  482.  
  483.         if Image.DEBUG:
  484.             print '- raw mode:', rawmode
  485.             print '- pil mode:', self.mode
  486.         
  487.         self.info['compression'] = self._compression
  488.         xdpi = getscalar(X_RESOLUTION, (1, 1))
  489.         ydpi = getscalar(Y_RESOLUTION, (1, 1))
  490.         if xdpi and ydpi and getscalar(RESOLUTION_UNIT, 1) == 1:
  491.             if not xdpi[1]:
  492.                 pass
  493.             xdpi = xdpi[0] / 1
  494.             if not ydpi[1]:
  495.                 pass
  496.             ydpi = ydpi[0] / 1
  497.             self.info['dpi'] = (xdpi, ydpi)
  498.         
  499.         x = y = l = 0
  500.         self.tile = []
  501.         if self.tag.has_key(STRIPOFFSETS):
  502.             h = getscalar(ROWSPERSTRIP, ysize)
  503.             w = self.size[0]
  504.             a = None
  505.             for o in self.tag[STRIPOFFSETS]:
  506.                 if not a:
  507.                     a = self._decoder(rawmode, l)
  508.                 
  509.                 self.tile.append((self._compression, (0, min(y, ysize), w, min(y + h, ysize)), o, a))
  510.                 y = y + h
  511.                 if y >= self.size[1]:
  512.                     x = y = 0
  513.                     l = l + 1
  514.                     a = None
  515.                     continue
  516.             
  517.         elif self.tag.has_key(324):
  518.             w = getscalar(322)
  519.             h = getscalar(323)
  520.             a = None
  521.             for o in self.tag[324]:
  522.                 if not a:
  523.                     a = self._decoder(rawmode, l)
  524.                 
  525.                 self.tile.append((self._compression, (x, y, x + w, y + h), o, a))
  526.                 x = x + w
  527.                 if x >= self.size[0]:
  528.                     x = 0
  529.                     y = y + h
  530.                     if y >= self.size[1]:
  531.                         x = y = 0
  532.                         l = l + 1
  533.                         a = None
  534.                     
  535.                 y >= self.size[1]
  536.             
  537.         elif Image.DEBUG:
  538.             print '- unsupported data organization'
  539.         
  540.         raise SyntaxError('unknown data organization')
  541.         if self.mode == 'P':
  542.             palette = map((lambda a: chr(a / 256)), self.tag[COLORMAP])
  543.             self.palette = ImagePalette.raw('RGB;L', string.join(palette, ''))
  544.         
  545.  
  546.  
  547. SAVE_INFO = {
  548.     '1': ('1', 1, 1, (1,), None),
  549.     'L': ('L', 1, 1, (8,), None),
  550.     'LA': ('LA', 1, 1, (8, 8), 2),
  551.     'P': ('P', 3, 1, (8,), None),
  552.     'PA': ('PA', 3, 1, (8, 8), 2),
  553.     'I': ('I;32S', 1, 2, (32,), None),
  554.     'I;16': ('I;16', 1, 1, (16,), None),
  555.     'I;16S': ('I;16S', 1, 2, (16,), None),
  556.     'F': ('F;32F', 1, 3, (32,), None),
  557.     'RGB': ('RGB', 2, 1, (8, 8, 8), None),
  558.     'RGBX': ('RGBX', 2, 1, (8, 8, 8, 8), 0),
  559.     'RGBA': ('RGBA', 2, 1, (8, 8, 8, 8), 2),
  560.     'CMYK': ('CMYK', 5, 1, (8, 8, 8, 8), None),
  561.     'YCbCr': ('YCbCr', 6, 1, (8, 8, 8), None),
  562.     'LAB': ('LAB', 8, 1, (8, 8, 8), None) }
  563.  
  564. def _cvt_res(value):
  565.     if type(value) in (type([]), type(())):
  566.         if not len(value) % 2 == 0:
  567.             raise AssertionError
  568.         return value
  569.     
  570.     if type(value) == type(1):
  571.         return (value, 1)
  572.     
  573.     value = float(value)
  574.     return (int(value * 65536), 65536)
  575.  
  576.  
  577. def _save(im, fp, filename):
  578.     
  579.     try:
  580.         (rawmode, photo, format, bits, extra) = SAVE_INFO[im.mode]
  581.     except KeyError:
  582.         raise IOError, 'cannot write mode %s as TIFF' % im.mode
  583.  
  584.     ifd = ImageFileDirectory()
  585.     fp.write(ifd.prefix + ifd.o16(42) + ifd.o32(8))
  586.     ifd[IMAGEWIDTH] = im.size[0]
  587.     ifd[IMAGELENGTH] = im.size[1]
  588.     if hasattr(im, 'tag'):
  589.         for key in (RESOLUTION_UNIT, X_RESOLUTION, Y_RESOLUTION):
  590.             if im.tag.tagdata.has_key(key):
  591.                 ifd[key] = im.tag.tagdata.get(key)
  592.                 continue
  593.         
  594.     
  595.     if im.encoderinfo.has_key('description'):
  596.         ifd[IMAGEDESCRIPTION] = im.encoderinfo['description']
  597.     
  598.     if im.encoderinfo.has_key('resolution'):
  599.         ifd[X_RESOLUTION] = ifd[Y_RESOLUTION] = _cvt_res(im.encoderinfo['resolution'])
  600.     
  601.     if im.encoderinfo.has_key('x resolution'):
  602.         ifd[X_RESOLUTION] = _cvt_res(im.encoderinfo['x resolution'])
  603.     
  604.     if im.encoderinfo.has_key('y resolution'):
  605.         ifd[Y_RESOLUTION] = _cvt_res(im.encoderinfo['y resolution'])
  606.     
  607.     if im.encoderinfo.has_key('resolution unit'):
  608.         unit = im.encoderinfo['resolution unit']
  609.         if unit == 'inch':
  610.             ifd[RESOLUTION_UNIT] = 2
  611.         elif unit == 'cm' or unit == 'centimeter':
  612.             ifd[RESOLUTION_UNIT] = 3
  613.         else:
  614.             ifd[RESOLUTION_UNIT] = 1
  615.     
  616.     if im.encoderinfo.has_key('software'):
  617.         ifd[SOFTWARE] = im.encoderinfo['software']
  618.     
  619.     if im.encoderinfo.has_key('date time'):
  620.         ifd[DATE_TIME] = im.encoderinfo['date time']
  621.     
  622.     if im.encoderinfo.has_key('artist'):
  623.         ifd[ARTIST] = im.encoderinfo['artist']
  624.     
  625.     if im.encoderinfo.has_key('copyright'):
  626.         ifd[COPYRIGHT] = im.encoderinfo['copyright']
  627.     
  628.     dpi = im.encoderinfo.get('dpi')
  629.     if dpi:
  630.         ifd[RESOLUTION_UNIT] = 1
  631.         ifd[X_RESOLUTION] = _cvt_res(dpi[0])
  632.         ifd[Y_RESOLUTION] = _cvt_res(dpi[1])
  633.     
  634.     if bits != (1,):
  635.         ifd[BITSPERSAMPLE] = bits
  636.         if len(bits) != 1:
  637.             ifd[SAMPLESPERPIXEL] = len(bits)
  638.         
  639.     
  640.     if extra is not None:
  641.         ifd[EXTRASAMPLES] = extra
  642.     
  643.     if format != 1:
  644.         ifd[SAMPLEFORMAT] = format
  645.     
  646.     ifd[PHOTOMETRIC_INTERPRETATION] = photo
  647.     if im.mode == 'P':
  648.         lut = im.im.getpalette('RGB', 'RGB;L')
  649.         ifd[COLORMAP] = tuple(map((lambda v: ord(v) * 256), lut))
  650.     
  651.     stride = len(bits) * ((im.size[0] * bits[0] + 7) / 8)
  652.     ifd[ROWSPERSTRIP] = im.size[1]
  653.     ifd[STRIPBYTECOUNTS] = stride * im.size[1]
  654.     ifd[STRIPOFFSETS] = 0
  655.     ifd[COMPRESSION] = 1
  656.     offset = ifd.save(fp)
  657.     ImageFile._save(im, fp, [
  658.         ('raw', (0, 0) + im.size, offset, (rawmode, stride, 1))])
  659.  
  660. Image.register_open('TIFF', TiffImageFile, _accept)
  661. Image.register_save('TIFF', _save)
  662. Image.register_extension('TIFF', '.tif')
  663. Image.register_extension('TIFF', '.tiff')
  664. Image.register_mime('TIFF', 'image/tiff')
  665.